﻿using MvCameraControl;
using SDKHKApp.SDK;

namespace MyCamera
{
    // 相机基础功能实现类
    public abstract class BaseCamera : ICamera
    {
        #region 相机参数
        /// <summary>
        /// 相机序列号
        /// </summary>
        public string SN { get; set; } = string.Empty;
        /// <summary>
        /// 是否正在取图
        /// </summary>
        public bool isGrabbing = false;
        /// <summary>
        /// 是否正在录像
        /// </summary>
        public bool isRecord = false;
        /// <summary>
        /// 图像采集对应委托
        /// </summary>
        public Action<string, Bitmap> ActionGetImage { get; set; }

        protected Bitmap CallBackImg { get; set; }
        #endregion

        #region 初始化
        public BaseCamera() { }
        #endregion

        #region  相机操作

        public abstract bool CloseDevice();

        public abstract List<string> GetListEnum();

        // 初始化并连接相机
        public abstract bool InitDevice(string CamSN);

        /// <summary>
        /// 基于软触发模式
        /// </summary>
        /// <returns></returns>
        public bool StartWith_SoftTriggerModel()
        {
            SetTriggerMode(TriggerMode.Off, TriggerSource.Software);
            return StartGrabbing();
        }

        /// <summary>
        /// 基于硬触发模式
        /// </summary>
        /// <param name="hardtriggeritem"></param>
        /// <returns></returns>
        public bool StartWith_HardTriggerModel(TriggerSource hardtriggeritem)
        {
            if (hardtriggeritem == TriggerSource.Software) hardtriggeritem = TriggerSource.Line0;
            SetTriggerMode(TriggerMode.On, hardtriggeritem);
            return StartGrabbing();
        }

        /// <summary>
        /// 等待硬触发获取图像
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="outtime"></param>
        /// <returns></returns>
        public bool GetImage(out Bitmap bitmap, int outtime = 3000)
        {
            bitmap = null;
            // 开始时间
            DateTime startTime = DateTime.Now; // 当前时间
            // 设置超时时间
            DateTime lastTime = startTime.AddMilliseconds(outtime);

            // 判断是否超时
            while (lastTime > DateTime.Now)// 设置超时时间为 3 秒
            {
                if (CallBackImg != null)
                {
                    bitmap = this.CallBackImg.Clone() as Bitmap;
                    CallBackImg = null;
                    break;
                }
            }
            return false;
        }

        /// <summary>
        /// 软触发获取图像
        /// </summary>
        /// <param name="bitmap"></param>
        /// <param name="outtime"></param>
        /// <returns></returns>
        public bool GetImageWithSoftTrigger(out Bitmap bitmap, int outtime = 3000)
        {
            if (!isGrabbing) 
            {
                StartGrabbing();
            }

            // 开始时间
            DateTime startTime = DateTime.Now; // 当前时间
            // 设置超时时间
            DateTime lastTime = startTime.AddMilliseconds(outtime);

            // 判断是否超时
            while (lastTime > DateTime.Now)// 设置超时时间为 3 秒
            {
                if (isGrabbing) 
                {
                    break;
                }
                    
            }
            // 获取当前触发模式
            GetTriggerMode(out TriggerMode triggerMode, out TriggerSource triggerSource);
            // 设置为软触发模式
            SetTriggerMode(TriggerMode.On, TriggerSource.Software);

            bitmap = null;
            if (!SoftTrigger()) { return false; };
            // 获取当前触发采集图像
            GetImage(out bitmap, outtime);
            // 重新设置为原来的触发模式
            SetTriggerMode(triggerMode, triggerSource);
            // 必须停止采集
            StopGrabbing();
            return (bitmap != null);
        }

        /// <summary>
        /// 软触发
        /// </summary>
        /// <returns></returns>
        public abstract bool SoftTrigger();
        #endregion

        #region 相机配置
        /// <summary>
        /// 设置相机配置
        /// </summary>
        /// <param name="config"></param>
        public void SetCamConfig(CamConfig config)
        {
            if (config == null) return;
            SetExpouseTime(config.ExpouseTime);
            SetTriggerMode(config.triggerMode, config.triggeSource);
            //SetTriggerPolarity(config.triggerPolarity);
            //SetTriggerFliter(config.TriggerFilter);
            SetGain(config.Gain);
            SetTriggerDelay(config.TriggerDelay);
        }

        /// <summary>
        /// 获取相机配置
        /// </summary>
        /// <param name="config"></param>
        public void GetCamConfig(out CamConfig config)
        {
            GetExpouseTime(out float expouseTime);
            GetTriggerMode(out TriggerMode triggerMode, out TriggerSource hardwareTriggerModel);
            //GetTriggerPolarity(out TriggerPolarity triggerPolarity);
            GetTriggerFliter(out float triggerfilter);
            GetGain(out float gain);
            GetTriggerDelay(out float triggerdelay);

            config = new CamConfig()
            {
                triggerMode = triggerMode,
                triggeSource = hardwareTriggerModel,
                //triggerPolarity = triggerPolarity,
                TriggerFilter = triggerfilter,
                TriggerDelay = triggerdelay,
                ExpouseTime = expouseTime,
                Gain = gain
            };
        }

        /// <summary>
        /// 设置触发模式及触发源
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="triggerEnum"></param>
        /// <returns></returns>
        public abstract bool SetTriggerMode(TriggerMode mode, TriggerSource triggerEnum = TriggerSource.Line0);
        /// <summary>
        /// 获取触发模式及触发源
        /// </summary>
        /// <param name="mode"></param>
        /// <param name="hardTriggerModel"></param>
        /// <returns></returns>
        public abstract bool GetTriggerMode(out TriggerMode mode, out TriggerSource hardTriggerModel);
        /// <summary>
        /// 设置曝光时间
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public abstract bool SetExpouseTime(float value);
        /// <summary>
        /// 获取曝光时间
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public abstract bool GetExpouseTime(out float value);

        /// <summary>
        /// 设置增益值
        /// </summary>
        /// <param name="gain"></param>
        /// <returns></returns>
        public abstract bool SetGain(float gain);
        /// <summary>
        /// 获取增益值
        /// </summary>
        /// <param name="gain"></param>
        /// <returns></returns>
        public abstract bool GetGain(out float gain);

        /// <summary>
        /// 获取帧率
        /// </summary>
        /// <param name="frameRate"></param>
        /// <returns></returns>
        public abstract bool GetFrameRate(out float frameRate);
        /// <summary>
        /// 设置帧率
        /// </summary>
        /// <param name="frameRate"></param>
        /// <returns></returns>
        public abstract bool SetFrameRate(float frameRate);
        /// <summary>
        /// 获取像素格式
        /// </summary>
        /// <param name="pixelFormats"></param>
        /// <returns></returns>
        public abstract bool GetPixelFormat(out List<string> pixelFormats);

        public abstract bool SetTriggerPolarity(TriggerPolarity polarity);

        public abstract bool GetTriggerPolarity(out TriggerPolarity polarity);

        /// <summary>
        /// 设置触发滤波时间 （us）
        /// </summary>
        /// <param name="flitertime"></param>
        /// <returns></returns>
        public abstract bool SetTriggerFliter(float flitertime);

        /// <summary>
        /// 获取触发参数时间 （us）
        /// </summary>
        /// <param name="flitertime"></param>
        /// <returns></returns>
        public abstract bool GetTriggerFliter(out float flitertime);
        public abstract bool SetTriggerDelay(float delay);
        public abstract bool GetTriggerDelay(out float delay);
        public abstract bool SetLineMode(IOLines line, LineMode mode);
        public abstract bool SetLineStatus(IOLines line, LineStatus linestatus);
        public abstract bool GetLineStatus(IOLines line, out LineStatus lineStatus);
        /// <summary>
        /// 自动白平衡
        /// </summary>
        /// <returns></returns>
        public abstract bool AutoBalanceWhite();
        #endregion

        #region  相机采集相关的方法
        /// <summary>
        /// 开始采图
        /// </summary>
        /// <returns></returns>
        public abstract bool StartGrabbing();
        /// <summary>
        /// 停止采图
        /// </summary>
        /// <returns></returns>
        public abstract bool StopGrabbing();
        /// <summary>
        /// 开始录像
        /// </summary>
        /// <returns></returns>
        public abstract bool StartRecord();
        /// <summary>
        /// 停止录像
        /// </summary>
        /// <returns></returns>
        public abstract bool StopRecord();
        /// <summary>
        /// 资源释放
        /// </summary>
        public abstract void Dispose();
        #endregion

        #region 图像保存
        /// <summary>
        /// 保存Bmp图像
        /// </summary>
        /// <returns></returns>
        public abstract bool SaveBmp();
        /// <summary>
        /// 保存Jpg图像
        /// </summary>
        /// <returns></returns>
        public abstract bool SaveJpg();
        /// <summary>
        /// 保存Png图像
        /// </summary>
        /// <returns></returns>
        public abstract bool SavePng();
        /// <summary>
        /// 保存Tiff图像
        /// </summary>
        /// <returns></returns>
        public abstract bool SaveTiff();
        #endregion
    }
}


